/**
 *  created by lllwx
 *  Date: 2021/6/2
 *  Time: 1:51 下午
 *  Version: 1.0
 *  For:
 */
import axios from 'axios';
import { message } from 'ant-design-vue';
import qs from 'qs';
import { HTTP_STATUS } from '@/common';

const successCode = [HTTP_STATUS.ACCEPTED, HTTP_STATUS.CREATED, HTTP_STATUS.SUCCESS];

const serverErrorCode = [HTTP_STATUS.SERVER_ERROR, HTTP_STATUS.GATEWAY_TIMEOUT, HTTP_STATUS.BAD_GATEWAY, HTTP_STATUS.SERVICE_UNAVAILABLE];

// 当前缓存的pending状态的请求
export const pendingRequest = [];

export const jsonType = {
  'content-type': 'application/json',
};

export const formType = {
  'content-type': 'application/x-www-form-urlencoded',
};

export const fileType = {
  'content-type': 'multipart/form-data',
};

export class Request {
  // 唯一实例
   static instance

   // // 请求对象
   service

   // 单例获取
   static getInstance() {
     this.instance || (this.instance = new Request());

     return this.instance;
   }

   constructor() {
     this.service = axios.create({
       baseURL: process.env.VUE_APP_BASE_URL,
       timeout: Number.parseInt(process.env.VUE_APP_TIME_OUT, 10),
       routeChangeCancel: true,
     });
     this.requestInterceptors();
     this.responseInterceptors();
   }

   // 请求拦截
   requestInterceptors() {
     this.service.interceptors.request.use(
       async (config) => {
         // 请求标志
         const requestMark = `${config.url}${config.method}`;
         const source = axios.CancelToken.source();
         config.cancelToken = source.token;
         config.requestMark = requestMark;
         // 加入到pending请求队列中
         pendingRequest.push({
           mark: requestMark,
           cancel: source.cancel,
           // 是否在切换路由取消请求 默认true
           routeChangeCancel: !!config.routeChangeCancel,
         });
         return config;
       },
       (error) => Promise.reject(error),
     );
   }

   // 响应拦截
   responseInterceptors() {
     this.service.interceptors.response.use(
       (response) => {
         // 从pending请求队列删除
         const markIndex = pendingRequest.findIndex((item) => item.mark === response.config.requestMark);
         markIndex !== -1 && pendingRequest.splice(markIndex, 1);
         // 200
         if (successCode.indexOf(response.status) !== -1) {
           // 接口返回200
           if (successCode.indexOf(Number(response.data.code)) !== -1) {
             return response.data.data;
           }
           message.error(response.data.message, 2);

           return Promise.reject(response.data);

         }
         if (serverErrorCode.indexOf(response.status) !== -1) {
           // TODO 服务器错误
           message.error('网络繁忙');
         } else {
           // TODO 请求错误
         }
       },
       (error) => Promise.reject(error),
     );
   }

   /**
   * @description get请求
   * @param {string} url
   * @param params
   * @param {object} config
   * @returns {Promise<AxiosResponse<T>>}
   */
   async get(url, params = {}, config = {}) {
     return await this.service.get(url, {
       ...config,
       params,
     });
   }

   /**
   * @description post 请求
   * @param {string} url
   * @param data
   * @param {object} header
   * @returns {Promise<AxiosResponse<T>>}
   */
   async post(url, data = {}, header = { ...formType }) {
     if (header['content-type'] === 'application/x-www-form-urlencoded') {
       data = qs.stringify(data);
     }
     return await this.service.post(url, data, {
       headers: header,
     });
   }

   /**
   * @description delete 请求
   * @param {string} url
   * @param params
   * @returns {Promise<T>}
   */
   async delete(url, params = {}) {
     return await this.service.delete(url, {
       params,
     });
   }
}
